home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
psi110g.zip
/
IPCMD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-26
|
21KB
|
745 lines
/* IP-related user commands
* Copyright 1991 Phil Karn, KA9Q
*/
/* Mods by PA0GRI */
#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "timer.h"
#include "netuser.h"
#include "iface.h"
#include "session.h"
#include "ip.h"
#include "cmdparse.h"
#include "commands.h"
#include "rip.h"
#include "rspf.h"
#include "domain.h"
#include "pktdrvr.h"
#include "socket.h"
int32 Ip_addr;
#ifdef __GNUC__
int Route_Sort = 1;
#else
extern int Route_Sort=1;
#endif
static int doadd __ARGS((int argc,char *argv[],void *p));
#ifdef IPACCESS
static int doaccess __ARGS((int argc,char *argv[],void *p));
#endif
static int dodrop __ARGS((int argc,char *argv[],void *p));
static int doflush __ARGS((int argc,char *argv[],void *p));
static int doipaddr __ARGS((int argc,char *argv[],void *p));
static int doipstat __ARGS((int argc,char *argv[],void *p));
static int dolook __ARGS((int argc,char *argv[],void *p));
static int dortimer __ARGS((int argc,char *argv[],void *p));
static int dottl __ARGS((int argc,char *argv[],void *p));
int doipheard __ARGS((int argc,char *argv[],void *p));
static int doiphport __ARGS((int argc,char *argv[],void *p));
static int doiphsize __ARGS((int argc,char *argv[],void *p));
void dumproute __ARGS((struct route *rp,char *p));
static int doroutesort __ARGS((int argc,char *argv[],void *p));
static struct cmds DFAR Ipcmds[] = {
#ifdef IPACCESS
"access", doaccess, 0, 0, NULLCHAR,
#endif
"address", doipaddr, 0, 0, NULLCHAR,
"heard", doipheard, 0, 0, NULLCHAR,
"hport", doiphport, 0, 0, NULLCHAR,
"hsize", doiphsize, 0, 0, NULLCHAR,
"rtimer", dortimer, 0, 0, NULLCHAR,
"status", doipstat, 0, 0, NULLCHAR,
"ttl", dottl, 0, 0, NULLCHAR,
NULLCHAR,
};
/* "route" subcommands */
static struct cmds Rtcmds[] = {
"add", doadd, 0, 3,
"route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
"addprivate", doadd, 0, 3,
"route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
"drop", dodrop, 0, 2,
"route drop <dest addr>[/<bits>]",
"flush", doflush, 0, 0,
NULLCHAR,
"lookup", dolook, 0, 2,
"route lookup <dest addr>",
"sort", doroutesort, 0, 0,
NULLCHAR,
NULLCHAR,
};
int
doip(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Ipcmds,argc,argv,p);
}
#ifdef IPACCESS
static int
doaccess(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
int32 source,target;
unsigned sbits,tbits;
char *bitp;
int16 lport,hport,protocol,state;
char *cp; /* for printing the table */
struct rtaccess *tpacc;
struct rtaccess *btacc;
struct rtaccess *bfacc;
struct rtaccess *head;
char tmpbuf[15];
if(argc == 1){ /* print out the table */
tputs("Source Address Len Dest Address Len Interface Proto Low High State\n");
for(tpacc = IPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtiface){
for(btacc = tpacc;btacc != NULLACCESS;btacc = btacc->nxtbits){
if(btacc->source != 0)
cp = inet_ntoa(btacc->source);
else
cp = "all";
tprintf("%-16s",cp);
tprintf("%2u ",btacc->sbits);
if(btacc->target != 0)
cp = inet_ntoa(btacc->target);
else
cp = "all";
tprintf("%-16s",cp);
tprintf("%2u ",btacc->bits);
tprintf("%-13s",btacc->iface->name);
switch (btacc->protocol) {
case 0:
cp = "any";
break;
case ICMP_PTCL:
cp = "icmp";
break;
case TCP_PTCL:
cp = "tcp";
break;
case UDP_PTCL:
cp = "udp";
break;
default:
cp = itoa(btacc->protocol,tmpbuf,10);
}
tprintf("%-5s ",cp);
tprintf("%5u ",btacc->lowport);
tprintf("%5u ",btacc->highport);
if(btacc->status)
cp = "deny";
else
cp = "permit";
tprintf("%-6s\n",cp);
}
}
return 0;
}
if(strcmp(argv[1],"permit") == 0){
state = 0;
} else {
if((strcmp(argv[1],"deny") == 0)
|| (strcmp(argv[1],"delete") == 0)){
state = -1;
} else {
tputs(" Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n");
return 1;
}
}
switch (*argv[2]){
case 'a': /* ANY */
protocol = 0;
break;
case 'i': /* ICMP */
protocol = ICMP_PTCL;
break;
case 't': /* TCP */
protocol = TCP_PTCL;
break;
case 'u': /* UDP */
protocol = UDP_PTCL;
break;
default:
protocol = atoi(argv[2]);
}
if(strcmp(argv[3],"all") == 0){
source = 0;
sbits = 0;
} else {
/* If IP address is followed by an optional slash and
* a length field, (e.g., 128.96/16) get it;
* otherwise assume a full 32-bit address
*/
if((bitp = strchr(argv[3],'/')) != NULLCHAR){
/* Terminate address token for resolve() call */
*bitp++ = '\0';
sbits = atoi(bitp);
} else
sbits = 32;
if((source = resolve(argv[3])) == 0){
tprintf(Badhost,argv[3]);
return 1;
}
}
if(strcmp(argv[4],"all") == 0){
target = 0;
tbits = 0;
} else {
if((bitp = strchr(argv[4],'/')) != NULLCHAR){
*bitp++ = '\0';
tbits = atoi(bitp);
} else
tbits = 32;
if((target = resolve(argv[4])) == 0){
tprintf(Badhost,argv[4]);
return 1;
}
}
if((ifp = if_lookup(argv[5])) == NULLIF){
tprintf(Badinterface,argv[5]);
return 1;
}
if(((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
lport = 0;
hport = 0;
} else {
if(strcmp(argv[6],"all") == 0){
lport = 0;
} else {
lport = atoi(argv[6]);
}
if((argc < 8) || (lport == 0))
hport = lport;
else
hport = atoi(argv[7]);
}
if(strcmp(argv[1],"delete") == 0){
head = IPaccess;
for(tpacc = IPaccess;tpacc != NULLACCESS;head = tpacc,tpacc = tpacc->nxtiface){
if(tpacc->iface == ifp){
for(btacc = tpacc;btacc != NULLACCESS;
head = btacc,btacc = btacc->nxtbits){
if((btacc->protocol == protocol) &&
(btacc->source == source) &&
(btacc->sbits == sbits) &&
(btacc->target == target) &&
(btacc->bits == tbits) &&
(btacc->lowport == lport) &&
(btacc->highport == hport)) { /*match*/
bfacc = btacc; /* save to unalloc */
/*now delete. watch for special cases*/
if(btacc != tpacc){ /* not at head of list */
head->nxtbits = btacc->nxtbits;
free(bfacc);
return 0;
}
if(btacc == IPaccess){ /* real special case */
if(IPaccess->nxtbits == NULLACCESS)
IPaccess = btacc->nxtiface;
else {
IPaccess = btacc->nxtbits;
(btacc->nxtbits)->nxtiface = btacc->nxtiface;
}
} else { /* we know tpacc=btacc <> IPaccess */
if(btacc->nxtbits == NULLACCESS)
head->nxtiface = btacc->nxtiface;
else {
head->nxtiface = btacc->nxtbits;
(btacc->nxtbits)->nxtiface = btacc->nxtiface;
}
}
free(bfacc);
return 0;
}
}
}
}
tputs("Not found.\n");
return 1;
}
/* add the access */
addaccess(protocol,source,sbits,target,tbits,ifp,lport,hport,state);
return 0;
}
#endif
static int
doipaddr(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 n;
if(argc < 2) {
tprintf("%s\n",inet_ntoa(Ip_addr));
} else if((n = resolve(argv[1])) == 0){
tprintf(Badhost,argv[1]);
return 1;
} else
Ip_addr = n;
return 0;
}
static int
dortimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&ipReasmTimeout,"IP reasm timeout (sec)",argc,argv);
}
static int
dottl(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&ipDefaultTTL,"IP Time-to-live",argc,argv);
}
char RouteHeader[] = "Destination Len Interface Gateway Metric P Timer Use\n";
/* Display and/or manipulate routing table */
int
doroute(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register int i,j,k,l,m,bits,flow_tmp;
register struct route *rp;
char *temp,temp2[80];
if(argc >= 2)
return subcmd(Rtcmds,argc,argv,p);
/* Dump IP routing table
* Dest Len Interface Gateway Use
* 192.001.002.003 32 sl0 192.002.003.004 0
* modified for Sorted output - D. Crompton 2.92
*/
flow_tmp=Current->flowmode;
Current->flowmode=1;
tputs(RouteHeader);
for(j=0,bits=31;bits>=0;bits--)
for(i=0;i<HASHMOD;i++)
for(rp = Routes[bits][i];rp != NULLROUTE;j++,rp = rp->next);
if (j){
temp=mallocw(j*80);
for(bits=31,k=0;bits>=0;bits--)
for(i=0;i<HASHMOD;i++)
for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next,k+=80)
dumproute(rp,&temp[k]);
#ifdef LINUX
if (Route_Sort) qsort(temp,(size_t)j,80,(int (*)__ARGS((void*,void*))) strcmp);
#else
if (Route_Sort) qsort(temp,(size_t)j,80,(int (*) ()) strcmp);
#endif
for (i=0,k=4;i<j;i++,k+=80) {
tputs(&temp[k]);
if (tputc('\n') == EOF)
{
Current->flowmode=flow_tmp;
free(temp);
return 0;
}
}
free(temp);
}
if(R_default.iface != NULLIF){
dumproute(&R_default,temp2);
tprintf("%s\n",&temp2[4]);
}
Current->flowmode = flow_tmp;
return 0;
}
/* Dump a routing table entry */
void
dumproute(rp,temp)
register struct route *rp;
char *temp;
{
char *cp;
unsigned int a=0;
char *name;
if(rp->target != 0) {
if(DTranslate && (name = resolve_a(rp->target,!DVerbose)) != NULLCHAR) {
strcpy(temp,name);
free(name);
} else {
cp = inet_ntobos(rp->target);
sprintf(temp,"%4s",cp);
}
cp = inet_ntoa(rp->target);
} else {
strcpy(temp,"default"); /* Don't really matter, but avoid unknown value */
cp = "default";
}
a=4;
a+=sprintf(&temp[a],"%-16.16s ",cp);
a+=sprintf(&temp[a],"%-4u",rp->bits);
a+=sprintf(&temp[a],"%-9.9s ",rp->iface->name);
if(rp->gateway != 0)
cp = inet_ntoa(rp->gateway);
else
cp = "";
a+=sprintf(&temp[a],"%-16.16s ",cp);
a+=sprintf(&temp[a],"%-6lu ",rp->metric);
a+=sprintf(&temp[a],"%c ",(rp->flags & RTPRIVATE) ? 'P' : ' ');
if(rp->timer.state == TIMER_STOP){
if(rp->timer.duration == 1) a+=sprintf(&temp[a],"rspf ");
else a+=sprintf(&temp[a],"man ");
} else {
a+=sprintf(&temp[a],"%-7lu",read_timer(&rp->timer) / 1000L);
}
sprintf(&temp[a],"%lu",rp->uses);
}
/* Sort Route dump */
static int
doroutesort(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
extern int Route_Sort;
return setbool(&Route_Sort,"Route Sort flag",argc,argv);
}
/* Add an entry to the routing table
* E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
*/
static int
doadd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
int32 dest,gateway;
unsigned bits;
char *bitp;
int32 metric;
char private;
if(strncmp(argv[0],"addp",4) == 0)
private = 1;
else
private = 0;
if(strcmp(argv[1],"default") == 0){
dest = 0L;
bits = 0;
} else {
/* If IP address is followed by an optional slash and
* a length field, (e.g., 128.96/16) get it;
* otherwise assume a full 32-bit address
*/
if((bitp = strchr(argv[1],'/')) != NULLCHAR){
/* Terminate address token for resolve() call */
*bitp++ = '\0';
bits = atoi(bitp);
} else
bits = 32;
if((dest = resolve(argv[1])) == 0){
tprintf(Badhost,argv[1]);
return 1;
}
}
if((ifp = if_lookup(argv[2])) == NULLIF){
tprintf(Badinterface,argv[2]);
return 1;
}
metric = 1;
if(argc > 3){
/* Next "trick is needed to set the metric on subnets
* higher as the default 1 for rspf.
* route add subnet/bits iface default 10
*/
if(strcmp(argv[3],"direct") == 0){ /* N1BEE */
gateway = 0;
/* calculate a nice metric based on subnet mask size */
if(bits != 0 && bits < 32)
metric = (39 - bits) * 5 / 17;
} else {
if((gateway = resolve(argv[3])) == 0){
tprintf(Badhost,argv[3]);
return 1;
}
}
} else {
gateway = 0;
}
if (argc > 4)
metric = atol(argv[4]);
if(rt_add(dest,bits,gateway,ifp,metric,0,private) == NULLROUTE)
tputs("Can't add route\n");
#ifdef RSPF
if(!private)
rspfrouteupcall(dest,bits,gateway); /* Do an RSPF upcall */
#endif /* RSPF */
return 0;
}
/* Drop an entry from the routing table
* E.g., "drop 128.96/16
*/
static int
dodrop(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char *bitp;
unsigned bits;
int32 n;
if(strcmp(argv[1],"default") == 0){
n = 0L;
bits = 0;
} else {
/* If IP address is followed by an optional slash and length field,
* (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
*/
if((bitp = strchr(argv[1],'/')) != NULLCHAR){
/* Terminate address token for resolve() call */
*bitp++ = '\0';
bits = atoi(bitp);
} else
bits = 32;
if((n = resolve(argv[1])) == 0){
tprintf(Badhost,argv[1]);
return 1;
}
}
return rt_drop(n,bits);
}
/* Force a timeout on all temporary routes */
static int
doflush(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct route *rp;
struct route *rptmp;
int i,j;
if(R_default.timer.state == TIMER_RUN){
rt_drop(0,0); /* Drop default route */
}
for(i=0;i<HASHMOD;i++){
for(j=0;j<32;j++){
for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
rptmp = rp->next;
if(rp->timer.state == TIMER_RUN){
rt_drop(rp->target,rp->bits);
}
}
}
}
return 0;
}
static int
dolook(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct route *rp;
int32 addr;
char temp[80];
addr = resolve(argv[1]);
if(addr == 0){
tprintf(Badhost,argv[1]);
return 1;
}
if((rp = rt_lookup(addr)) == NULLROUTE){
tprintf("Host %s (%s) unreachable\n",argv[1],inet_ntoa(addr));
return 1;
}
dumproute(rp,temp);
tputs(RouteHeader);
tprintf("%s\n",&temp[4]);
return 0;
}
static int
doipstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct reasm *rp;
register struct frag *fp;
int i;
for(i=1;i<=NUMIPMIB;i++){
tprintf("(%2u)%-20s%10lu",i,
Ip_mib[i].name,Ip_mib[i].value.integer);
if(i % 2)
tputs(" ");
else
tputc('\n');
}
if((i % 2) == 0)
tputc('\n');
if(Reasmq != NULLREASM)
tputs("Reassembly fragments:\n");
for(rp = Reasmq;rp != NULLREASM;rp = rp->next){
tprintf("src %s",inet_ntoa(rp->source));
tprintf(" dest %s",inet_ntoa(rp->dest));
if(tprintf(" id %u pctl %u time %lu len %u\n",
rp->id,uchar(rp->protocol),read_timer(&rp->timer),
rp->length) == EOF)
break;
for(fp = rp->fraglist;fp != NULLFRAG;fp = fp->next){
if(tprintf(" offset %u last %u\n",fp->offset,
fp->last) == EOF)
break;
}
}
return 0;
}
/* IP heard logging - WG7J */
static struct iph *iph_create __ARGS((int32 addr));
static struct iph *iph_lookup __ARGS((int32 addr));
struct iph *Iph;
static int Maxipheard = MAXIPHEARD;
static int doiphsize(int argc,char *argv[],void *p) {
return setint(&Maxipheard,"Max ip-heard",argc,argv);
}
/* Configure a port to do ip-heard logging */
static int
doiphport(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setflag(argc,argv[1],LOG_IPHEARD,argv[2]);
}
int
doipheard(int argc,char *argv[],void *p) {
struct iph *iph;
if(tputs("Tcp/Ip systems heard:\n"
"Address Port Since Pkts\n") == EOF)
return EOF;
for(iph=Iph;iph;iph=iph->next) {
if(tprintf("%-22s %-8s %12s %5ld\n",inet_ntoa(iph->addr),iph->iface->name,
tformat(secclock() - iph->time),iph->count) == EOF)
return EOF;
}
return 0;
}
void
log_ipheard(int32 addr,struct iface *ifp) {
struct iph *niph;
if((niph = iph_lookup(addr)) == NULLIPH)
if((niph = iph_create(addr)) == NULLIPH)
return;
niph->iface = ifp;
niph->count++;
niph->time = secclock();
}
/* Look up an entry in the ip data base */
struct iph *
iph_lookup(addr)
int32 addr;
{
register struct iph *ip;
struct iph *last = NULLIPH;
for(ip = Iph;ip != NULLIPH;last = ip,ip = ip->next){
if(ip->addr == addr) {
if(last != NULLIPH){
/* Move entry to top of list */
last->next = ip->next;
ip->next = Iph;
Iph = ip;
}
return ip;
}
}
return NULLIPH;
}
/* Create a new entry in the source database */
/* If there are too many entries, override the oldest one - WG7J */
static struct iph *
iph_create(addr)
int32 addr;
{
static int numdb;
register struct iph *iph;
struct iph *last = NULLIPH;
if(Maxipheard && numdb == Maxipheard) {
/* find and use last one in list */
for(iph = Iph;iph->next != NULLIPH;last = iph,iph = iph->next);
/* delete entry from end */
last->next = NULLIPH;
} else { /* create a new entry */
numdb++;
iph = (struct iph *)callocw(1,sizeof(struct iph));
}
iph->addr = addr;
iph->count = 0; /* VE3DTE */
iph->next = Iph;
Iph = iph;
return iph;
}